#include "ViewTexture.h"
#include "../../Utils/LogUtil.h"
#include "../../Core/CoreGlobals.h"
#include "../RenderState.h"
#include "../../Game/Process/RenderProcess.h"

ViewTexture::BuilderDetails::BuilderDetails()
{
	viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
	components = { VK_COMPONENT_SWIZZLE_R , VK_COMPONENT_SWIZZLE_G , VK_COMPONENT_SWIZZLE_B , VK_COMPONENT_SWIZZLE_A };
	subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
	subresourceRange.baseMipLevel = 0;
	subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
	subresourceRange.baseArrayLayer = 0;
	subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
}

ViewTexture::Builder::Builder() noexcept = default;
ViewTexture::Builder::~Builder() noexcept = default;
ViewTexture::Builder::Builder(ViewTexture::Builder const& rhs) noexcept = default;
ViewTexture::Builder::Builder(ViewTexture::Builder && rhs) noexcept = default;
ViewTexture::Builder& ViewTexture::Builder::operator=(ViewTexture::Builder const& rhs) noexcept = default;
ViewTexture::Builder& ViewTexture::Builder::operator=(ViewTexture::Builder && rhs) noexcept = default;


ViewTexture::Builder& ViewTexture::Builder::SetTexture(RefCountPtr<RHITexture> texture) noexcept
{
	mImpl->texture = texture;
	return *this;
}

ViewTexture::Builder& ViewTexture::Builder::SetViewType(VkImageViewType viewType) noexcept
{
	mImpl->viewType = viewType;
	return *this;
}

ViewTexture::Builder& ViewTexture::Builder::SetComponents(VkComponentMapping components) noexcept
{
	mImpl->components = components;
	return *this;
}

ViewTexture::Builder& ViewTexture::Builder::SetAspectMask(VkImageAspectFlags aspectMask) noexcept
{
	mImpl->subresourceRange.aspectMask = aspectMask;
	return *this;
}

ViewTexture::Builder& ViewTexture::Builder::SetBaseMipLevel(uint32 baseMipLevel) noexcept
{
	mImpl->subresourceRange.baseMipLevel = baseMipLevel;
	return *this;
}

ViewTexture::Builder& ViewTexture::Builder::SetLevelCount(uint32 levelCount) noexcept
{
	mImpl->subresourceRange.levelCount = levelCount;
	return *this;
}

ViewTexture::Builder& ViewTexture::Builder::SetBaseArrayLayer(uint32 baseArrayLayer) noexcept
{
	mImpl->subresourceRange.baseArrayLayer = baseArrayLayer;
	return *this;
}

ViewTexture::Builder& ViewTexture::Builder::SetLayerCount(uint32 layerCount) noexcept
{
	mImpl->subresourceRange.layerCount = layerCount;
	return *this;
}

RefCountPtr<ViewTexture> ViewTexture::Builder::Build()
{
	assert(IsInRenderThread());
	return RefCountPtr<ViewTexture>(NewObject<ViewTexture>(*mImpl));
}

RefCountPtr<ViewTexture> ViewTexture::Builder::Build(RenderProcess * process, const std::string & name)
{
	assert(IsInRenderThread());
	ViewTexture* viewTexture = NewObject<ViewTexture>(*mImpl);
	process->AddTexture(name, viewTexture);
	return RefCountPtr<ViewTexture>(viewTexture);
}

void ViewTexture::ReleaseResource()
{
	if (IsInRenderThread())
	{
		if (mProcess != nullptr)
		{
			mProcess->RemoveTexture(mName, this);
		}
		DeleteObject<ViewTexture>(this);
	}
	else
	{
		AsyncTask(GRenderThreadId, [this]() {
			if (mProcess != nullptr)
			{
				mProcess->RemoveTexture(mName, this);
			}
			DeleteObject<ViewTexture>(this);
			});
	}
}

ViewTexture::ViewTexture(BuilderDetails & builderDetails)
{
	mIsMultiple = builderDetails.texture->IsMultiple();
	mIsRenderTarget = builderDetails.texture->IsRenderTarget();

	mFlags = builderDetails.texture->GetImageCreateFlags();
	mImageType = builderDetails.texture->GetImageType();
	mFormat = builderDetails.texture->GetFormat();
	mExtent = builderDetails.texture->GetExtent();
	mMipLevels = builderDetails.texture->GetMipLevels();
	mArrayLayers = builderDetails.texture->GetArrayLayers();
	mSamples = builderDetails.texture->GetSamples();
	mTiling = builderDetails.texture->GetTiling();
	mUsage = builderDetails.texture->GetUsage();
	mSharingMode = builderDetails.texture->GetSharingMode();
	mQueueFamilys = builderDetails.texture->GetQueueFamilys();

	mImageLayouts.resize(GetFrameCount(), builderDetails.texture->GetImageLayout());
	mMemoryProperty = builderDetails.texture->GetMemoryProperty();

	mViewType = builderDetails.viewType;
	if (mViewType == VK_IMAGE_VIEW_TYPE_MAX_ENUM)
		mViewType = builderDetails.texture->GetImageViewType();

	mComponents = builderDetails.components;
	mSubresourceRange = builderDetails.subresourceRange;
	if (mSubresourceRange.levelCount == VK_REMAINING_MIP_LEVELS)
	{
		mSubresourceRange.levelCount = mMipLevels;
	}
	if (mSubresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS)
	{
		mSubresourceRange.layerCount = mArrayLayers;
	}

	mImages.resize(GetFrameCount(), VK_NULL_HANDLE);
	mImageMemorys.resize(GetFrameCount(), VK_NULL_HANDLE);
	mImageViews.resize(GetFrameCount(), VK_NULL_HANDLE);

	for (uint32 i = 0; i < GetFrameCount(); ++i)
	{
		GVulkanRHI->CreateImageView(mImageViews[i], builderDetails.texture->GetImage(i), mFormat, mViewType, mSubresourceRange, mComponents);
	}
}

